package br.com.mlk.model;

import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import br.com.mlk.controller.AbstractEntity;

@SuppressWarnings("uncheked")
public class GenericDAO<T extends AbstractEntity> {

	protected EntityManager entityManager;
	protected EntityManagerFactory fac;
	
	public GenericDAO(){
		this.getEntityManager();
	}
	
	public  EntityManager getEntityManager(){
			fac = Persistence.createEntityManagerFactory("testedao");
			entityManager = fac.createEntityManager();
		return entityManager;
	}

	public T getById(Long id) {
		return (T) entityManager.find(getTypeClass(), id);
	}

	public void save(T entity) {
		try {
			this.getEntityManager();
			entityManager.getTransaction().begin();
			entityManager.persist(entity);
			entityManager.getTransaction().commit();
			entityManager.close();
			fac.close();
		} catch (Exception e) {
			e.printStackTrace();
			entityManager.getTransaction().rollback();
		}
	}

	public void update(T entity) {
		try {
			this.getEntityManager();
			entityManager.getTransaction().begin();
			entityManager.merge(entity);
			entityManager.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			entityManager.getTransaction().rollback();
		}

	}

	public void delete(T entity) {
		try {
			this.getEntityManager();
			entity = getById(entity.getId());
			entityManager.getTransaction().begin();
			entityManager.remove(entity);
			entityManager.getTransaction().commit();
			entityManager.close();
			fac.close();
		} catch (Exception e) {
			e.printStackTrace();
			entityManager.getTransaction().rollback();
		}
	}

	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		this.getEntityManager();
		return entityManager.createQuery(("From " + getTypeClass().getName()))
				.getResultList();
	}

	private Class<?> getTypeClass() {
		Class<?> clazz = (Class<?>) ((ParameterizedType) this.getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
		return clazz;
	}

}
